-
Notifications
You must be signed in to change notification settings - Fork 405
Fix Gen.pick producing only a subset of possible combinations #1119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a bug in the Gen.pick
method where incorrect operator precedence caused the random insertion index calculation to produce a biased distribution, resulting in only a subset of possible combinations being generated.
- Fixes operator precedence in random index calculation by adding parentheses around
(x & Long.MaxValue)
- Adds a test to verify that
Gen.pick
produces the expected number of distinct combinations
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
File | Description |
---|---|
core/shared/src/main/scala/org/scalacheck/Gen.scala | Fixes operator precedence bug in random index calculation |
core/jvm/src/test/scala/org/scalacheck/GenSpecification.scala | Adds test to verify correct number of distinct combinations are generated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thank you!
Looks like Gen.pick
didn't work properly all that time.
|
||
val genPick = pick(n, 1 to nElements) | ||
// not interested in different permutations, only in distinct combinations | ||
.map(_.toList.sorted) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, what is the reason for converting the output of pick
to List
before sorting it? It doesn't seem it is supposed to improve performance or affects the test in any other way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like a leftover from my attempts at writing this test. Removed it.
I think, at some point I had sets and also tried to collect the stats on those. It went into .toString
on sets which, amusingly, may be different for equal small sets (up to 4 elements). Thus, it ended up with aSet.toList.sorted
and later got scrapped, but toList
somehow survived 😅
// that every possible combination appears at least once. It depends on | ||
// nSamples, but there is no specific math behind it. Rather, it's just an | ||
// empirically chosen value, that has yielded no failures over thousands of | ||
// test cycles. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
…over thousands of test cycles.
Specifically this
+ Gen.pick produces enough distinct combinations: OK, passed 10000000 tests
I believe it is good to go, thanks! |
When calculating a random insertion index for an element
Gen.pick
uses wrong order of operationsAs written, it first gets the modulo
MaxValue & count
and then uses it to mask a randomx
to get a positive value. Instead it should mask thex
first, and only then get a modulo of it.This PR fixes the order of operations.